import numpy as np

from common.gradient import numerical_gradient


def softmax(x):
    max = np.max(x)
    exp_x = np.exp(x - max)
    sum_exp_x = np.sum(exp_x)
    return exp_x / sum_exp_x


def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)

        # 监督数据是one-hot-vector的情况下，转换为正确解标签的索引
    if t.size == y.size:
        t = t.argmax(axis=1)

    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size


class simleNet():
    def __init__(self):  # 权重矩阵初始化
        self.W = np.random.randn(2, 3)

    def predict(self, x):  # 推理
        y = np.dot(x, self.W)
        return y

    def loss(self, x, t):  # 损失函数计算
        y = self.predict(x=x)
        z = softmax(y)

        loss = cross_entropy_error(z, t)
        return loss


if __name__ == '__main__':
    x = np.array([0.6, 0.9])
    t = np.array([0, 0, 1])

    net = simleNet()

    f = lambda w: net.loss(x, t)
    dW = numerical_gradient(f, net.W)
    print('损失函数对于权重参数的偏导数矩阵是：')
    print(dW)
